package graph;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Map.Entry;

public class WeightedDirectedGraph<ItemType, CostType> {

	Map<ItemType, Vertex<ItemType, CostType>>	vertices	= new LinkedHashMap<ItemType, Vertex<ItemType, CostType>>();

	public WeightedDirectedGraph() {

	}

	public void putVertex(ItemType item) {
		vertices.put(item, new Vertex<ItemType, CostType>(item));
	}

	public void addEdge(CostType weight, ItemType item1, ItemType item2) {
		Vertex<ItemType, CostType> vertex1 = getVertex(item1);
		Vertex<ItemType, CostType> vertex2 = getVertex(item2);
		if (vertex1 != null && vertex2 != null) {
			vertex1.addSide(vertex2, weight);
		}
	}

	public CostType getCost(ItemType item1, ItemType item2) {
		Vertex<ItemType, CostType> vertex1 = getVertex(item1);
		if (vertex1 != null) {
			return vertex1.getCost(item2);
		}
		return null;
	}

	private Vertex<ItemType, CostType> getVertex(ItemType item) {
		return vertices.get(item);
	}

	public int getSize() {
		return vertices.size();
	}

	public ArrayList<Vertex<ItemType, CostType>> getBreadthFirst(ItemType item) {
		ArrayList<Vertex<ItemType, CostType>> vertexList = new ArrayList<Vertex<ItemType, CostType>>();
		ArrayList<Vertex<ItemType, CostType>> checkedList = new ArrayList<Vertex<ItemType, CostType>>();

		Vertex<ItemType, CostType> v = getVertex(item);
		if (v == null)
			return vertexList;
		return v.countBreadthFirst(vertexList, checkedList);
	}


	public ArrayList<Vertex<ItemType, CostType>> getDepthFirst(ItemType item) {
		ArrayList<Vertex<ItemType, CostType>> vertexList = new ArrayList<Vertex<ItemType, CostType>>();
		ArrayList<Vertex<ItemType, CostType>> checkedList = new ArrayList<Vertex<ItemType, CostType>>();

		Vertex<ItemType, CostType> v = getVertex(item);
		if (v == null)
			return vertexList;
		return v.countDepthFirst(vertexList, checkedList);
	}

	
	public ArrayList<Vertex<ItemType, CostType>> getAll(){
		Set<Entry<ItemType, Vertex<ItemType, CostType>>> set = vertices.entrySet();
		
		
		ArrayList<Vertex<ItemType, CostType>> list = new ArrayList<Vertex<ItemType, CostType>>();
		Iterator<Entry<ItemType, Vertex<ItemType, CostType>>> it = set.iterator();
		
		for (int i = 0; i < set.size(); i++) {
			Entry<ItemType, Vertex<ItemType, CostType>> pair = it.next();
			list.add(pair.getValue());
		}
		return list;
	}
	
	public String toString() {
		String returnString = "";
		Set<Entry<ItemType, Vertex<ItemType, CostType>>> set = vertices.entrySet();
		Iterator<Entry<ItemType, Vertex<ItemType, CostType>>> i = set.iterator();
		while (i.hasNext()) {
			Entry<ItemType, Vertex<ItemType, CostType>> pair = i.next();
			returnString += pair.getValue().toString();
			if (i.hasNext())
				returnString += "_";
		}
		return returnString;
	}

	// ??

	public void draw(Graphics g, int x, int y) {

		int[][] vertexPositions = new int[3][vertices.size()];
		String[] items = new String[vertices.size()];
	
		Random r = new Random();

		Set<Entry<ItemType, Vertex<ItemType, CostType>>> set = vertices.entrySet();
		ArrayList<Vertex<ItemType, CostType>> checkedList = new ArrayList<Vertex<ItemType, CostType>>();

		Iterator<Entry<ItemType, Vertex<ItemType, CostType>>> i = set.iterator();

		int dx = x;
		int dy = y;
		int num = 0;
		while (i.hasNext()) {
			dx += (r.nextInt(9) - 3) * 30 + 5;
			dy += (r.nextInt(9) - 3) * 30 + 5;
			Entry<ItemType, Vertex<ItemType, CostType>> pair = i.next();
			System.out.println(pair.getValue());
			vertexPositions[0][num] = dx;
			vertexPositions[1][num] = dy;
			vertexPositions[2][num] = pair.getValue().hashCode();
			items[num] = pair.getKey().toString();
			num++;
		}
		
		Iterator<Entry<ItemType, Vertex<ItemType, CostType>>> j = set.iterator();
		int nom = 0;
		while (j.hasNext()) {
		
			Entry<ItemType, Vertex<ItemType, CostType>> pair = j.next();
			Set<Vertex<ItemType, CostType>> neighs = pair.getValue().getNeighbours();
			for(Vertex<ItemType, CostType> vertex : neighs){
				for(int q = 0;q < vertices.size();q++){
					if(vertexPositions[2][q] == vertex.hashCode()){
						String b = pair.getValue().getCost(vertex.getItem()).toString();
					
						
						double dist = Math.sqrt((((double)vertexPositions[0][nom]-(double)vertexPositions[0][q])*((double)vertexPositions[1][nom]-(double)vertexPositions[1][q]))-(((double)vertexPositions[0][nom]-(double)vertexPositions[0][q])*((double)vertexPositions[1][nom]-(double)vertexPositions[1][q])));
						
						g.drawLine(vertexPositions[0][nom],vertexPositions[1][nom], vertexPositions[0][q], vertexPositions[1][q]);
						g.fillOval((int)((vertexPositions[0][q]*0.25+vertexPositions[0][nom]*0.75)-5), (int)((vertexPositions[1][q]*0.25+vertexPositions[1][nom]*0.75)-5), 10,10);
						g.drawString(Double.toString(dist),(int)((vertexPositions[0][q]*0.25+vertexPositions[0][nom]*0.75)-5), (int)((vertexPositions[1][q]*0.25+vertexPositions[1][nom]*0.75)-5));
					}
				}
			}
			nom++;
		}
		for (int b = 0; b < num; b++) {			
			
			g.drawOval(vertexPositions[0][b]-10, vertexPositions[1][b]-10, 20, 20);
			g.drawString(items[b],vertexPositions[0][b]+10,vertexPositions[1][b]+10);
			g.setColor(Color.BLACK);
		}

	}

}
